package pedro.rtsp.rtp.packets

import android.media.MediaCodec
import pedro.rtsp.utils.RtpConstants
import pedro.rtsp.utils.setLong
import java.nio.ByteBuffer
import java.util.*
import kotlin.experimental.and
import kotlin.experimental.or

/**
 * Created by pedro on 27/11/18.
 */
internal abstract class BasePacket(private val clock: Long, private val payloadType: Int) {

    protected var channelIdentifier: Byte = 0
    protected var rtpPort = 0
    protected var rtcpPort = 0
    private var seq = 0
    private var ssrc = Random().nextInt()
    protected val maxPacketSize = RtpConstants.MTU - 28
    protected val TAG = "BasePacket"

    abstract fun createAndSendPacket(byteBuffer: ByteBuffer, bufferInfo: MediaCodec.BufferInfo)

    fun setPorts(rtpPort: Int, rtcpPort: Int) {
        this.rtpPort = rtpPort
        this.rtcpPort = rtcpPort
    }

    open fun reset() {
        seq = 0
        ssrc = Random().nextInt()
    }

    protected fun getBuffer(size: Int): ByteArray {
        val buffer = ByteArray(size)
        buffer[0] = "10000000".toInt(2).toByte()
        buffer[1] = payloadType.toByte()
        setLongSSRC(buffer, ssrc)
        requestBuffer(buffer)
        return buffer
    }

    protected fun updateTimeStamp(buffer: ByteArray, timestamp: Long) {
        val ts = timestamp * clock / 1000000000L
        buffer.setLong(ts, 4, 8)
    }

    protected fun updateSeq(buffer: ByteArray) {
        buffer.setLong((++seq).toLong(), 2, 4)
    }

    protected fun markPacket(buffer: ByteArray) {
        buffer[1] = buffer[1] or (0x80).toByte()
    }

    private fun setLongSSRC(buffer: ByteArray, ssrc: Int) {
        buffer.setLong(ssrc.toLong(), 8, 12)
    }

    private fun requestBuffer(buffer: ByteArray) {
        buffer[1] = buffer[1] and 0x7F
    }
}